package com.xiaoka.flutter_plugin_gdmap.AMapPolygon;

import android.content.Context;
import android.graphics.Color;
import android.location.Location;
import android.util.Log;
import android.view.View;
import androidx.annotation.NonNull;
import com.amap.api.maps.AMap;
import com.amap.api.maps.CameraUpdateFactory;
import com.amap.api.maps.TextureMapView;
import com.amap.api.maps.UiSettings;
import com.amap.api.maps.model.CameraPosition;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.LatLngBounds;
import com.amap.api.maps.model.MyLocationStyle;
import com.amap.api.maps.model.Polygon;
import com.amap.api.maps.model.PolygonHoleOptions;
import com.amap.api.maps.model.PolygonOptions;
import com.amap.api.services.core.AMapException;
import com.amap.api.services.core.LatLonPoint;
import com.amap.api.services.core.PoiItem;
import com.amap.api.services.poisearch.PoiResult;
import com.amap.api.services.poisearch.PoiSearch;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.xiaoka.flutter_plugin_gdmap.Constant;
import com.xiaoka.flutter_plugin_gdmap.LittleUtils;
import com.xiaoka.flutter_plugin_gdmap.LocationBean;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.platform.PlatformView;

/**
 * Copyright (C), 2020 - 2999, Sichuan Xiaoka Technology Co., Ltd.
 *
 * @Description:地图控件
 * @Author: lch
 * @Date: 2020/10/23 16:36
 **/
public class AMapPolygonPluginView implements PlatformView, MethodChannel.MethodCallHandler {

    private final Context context;

    private MethodChannel mChannel;

    //地图视图
    private TextureMapView mMapView;

    //初始化地图控制器对象
    AMap aMap;

    //当前位置
    LatLng latLng = null;
    private UiSettings mUiSettings;//定义一个UiSettings对象
    private MyLocationStyle myLocationStyle;

    List<LatLng> latLngs;

    public AMapPolygonPluginView(BinaryMessenger binaryMessenger, int viewId, final Context context) {

        this.context = context;
        mChannel = new MethodChannel(binaryMessenger, Constant.AMAP_CHANNEL_NAME + "/amap_polygon"+viewId);
        mChannel.setMethodCallHandler(this);

        mMapView = new TextureMapView(context);
        mMapView.setBackgroundColor(Color.WHITE);
        Log.e("地图~~~~~~~~~~", "创建地图");
        mMapView.onCreate(null);//重要
        if (aMap == null) {
            aMap = mMapView.getMap();
        }
        latLngs = new ArrayList<>();

        //地图模式可选类型：MAP_TYPE_NORMAL(白昼地图（即普通地图）),MAP_TYPE_SATELLITE(卫星图),MAP_TYPE_NIGHT(夜景地图),MAP_TYPE_NAVI(导航地图)
        aMap.setMapType(AMap.MAP_TYPE_NORMAL);
        aMap.setTrafficEnabled(true);// 显示实时交通状况
        aMap.setMyLocationEnabled(true);// 设置为true表示启动显示定位蓝点，false表示隐藏定位蓝点并不进行定位，默认是false。

        /**定位蓝点**/
        myLocationStyle = new MyLocationStyle();//初始化定位蓝点样式类myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE);//连续定位、且将视角移动到地图中心点，定位点依照设备方向旋转，并且会跟随设备移动。（1秒1次定位）如果不设置myLocationType，默认也会执行此种模式。
        myLocationStyle.interval(3000); //设置连续定位模式下的定位间隔，只在连续定位模式下生效，单次定位模式下不会生效。单位为毫秒。
        myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE_NO_CENTER);//连续定位、蓝点不会移动到地图中心点，定位点依照设备方向旋转，并且蓝点会跟随设备移动。
        myLocationStyle.showMyLocation(true); //设置是否显示定位小蓝点，用于满足只想使用定位，不想使用定位小蓝点的场景，设置false以后图面上不再有定位蓝点的概念，但是会持续回调位置信息。
//        myLocationStyle.myLocationIcon(BitmapDescriptorFactory.fromResource(R.drawable.common_icon_location_blue));//自定义定位蓝点图标
//        myLocationStyle.anchor(0.5f, 0.5f);//自定义定位蓝点图标的锚点
        myLocationStyle.strokeColor(Color.argb(0, 0, 0, 0));// 设置圆形的边框颜色 这个颜色透明即不显示精度圆圈
        myLocationStyle.radiusFillColor(Color.argb(0, 0, 0, 0));// 设置圆形的填充颜色 这个颜色透明即不显示精度圆圈
        aMap.setMyLocationStyle(myLocationStyle);//设置定位蓝点的Style

        /**控件交互**/
        mUiSettings = aMap.getUiSettings();//实例化UiSettings类对象
        mUiSettings.setZoomControlsEnabled(false);//是否允许显示缩放按钮
        mUiSettings.setCompassEnabled(false);//指南针
        mUiSettings.setMyLocationButtonEnabled(false); //显示默认的定位按钮
        mUiSettings.setScaleControlsEnabled(false); //控制比例尺控件是否显示

        /**调用方法交互**/
//        aMap.animateCamera(CameraUpdateFactory.zoomTo(12);//缩放等级

        aMap.addOnMyLocationChangeListener(new AMap.OnMyLocationChangeListener() {
            @Override
            public void onMyLocationChange(Location location) {
                //从location对象中获取经纬度信息，地址描述信息
//                Log.e("地图～～～～～", "定位：" + location.getLatitude() + "～～～" + location.getLongitude());
                latLng = new LatLng(location.getLatitude(), location.getLongitude());
            }
        });

        //监听屏幕中心坐标
        aMap.setOnCameraChangeListener(cameraChangeListener);
    }

    @Override
    public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
        Log.e("地图~~~~~~~~~~", "插件接收到通信Method:" + call.method);

        if (call.method.equals("drawPolygon")) {
            //画围栏
            String listJson = call.argument("list").toString();
            Log.e("地图~~~~~~~~~~", "收到的数据: " + listJson);
            if (latLng == null) {
                latLng = new Gson().fromJson(call.argument("location").toString(), LatLng.class);
            }
            //围栏数据
            AMapPolygonBean bean = new Gson().fromJson(listJson, AMapPolygonBean.class);
            drawPolygon(bean, latLngs);
            latLngs.add(latLng);
            boundsZoom(latLngs);
            result.success(true);
        } else if (call.method.equals("goLocation")) {
            //主动回到定位点
            LatLng mylatLng = new Gson().fromJson(call.argument("location").toString(), LatLng.class);
            aMap.animateCamera(CameraUpdateFactory.changeLatLng(mylatLng));
            result.success(true);
        } else if (call.method.equals("polygonCon")) {
            //判断点是否在围栏内
            String listJson = call.argument("list").toString();
            List<LatLng> sortList = new Gson().fromJson(listJson, new TypeToken<List<LatLng>>() {
            }.getType());
            LatLng mylatLng = new Gson().fromJson(call.argument("location").toString(), LatLng.class);
            result.success(polygonCon(sortList, mylatLng));
        } else if (call.method.equals("polygonInside")) {
            //将屏幕中心定位到围栏内
            String listJson = call.argument("list").toString();
            //围栏数据
            AMapPolygonBean bean = new Gson().fromJson(listJson, AMapPolygonBean.class);

            polygonInside(bean);
        }else if (call.method.equals("setAllGestures")){
            //设置地图的手势是否开启
            boolean isEnabled = call.argument("isEnabled");
            aMap.getUiSettings().setAllGesturesEnabled(isEnabled);
        }else if (call.method.equals("setZoomTo")){
            //设置缩放等级
            //设置地图的手势是否开启
            int num = call.argument("num");
            //以动画方式按照传入的CameraUpdate参数更新地图状态，默认动画耗时250毫秒。
            // 所以不能连续使用animateCamera方法,只是得有一定的间隔
            aMap.animateCamera(CameraUpdateFactory.zoomTo(num));
        }
    }

    @Override
    public View getView() {
        return mMapView;
    }

    @Override
    public void dispose() {
        Log.e("地图~~~~~~~~~~", "地图控件销毁");
        if (mMapView != null) {
            mMapView.onDestroy();
        }

        if (mChannel != null) {
            mChannel.setMethodCallHandler(null);
        }
    }


    /** ～～～～～～～～～～～～～～～～～以下为定制内容 start～～～～～～～～～～～～～～～～～ **/

    /**
     * 画围栏
     *
     * @bean 围栏数据
     */
    public void drawPolygon(AMapPolygonBean bean, List<LatLng> latLngs) {
        PolygonOptions polygonOptions;
        PolygonHoleOptions polygonHoleOptions;
        List<LatLng> latLngHoles;

        List<List<List<AMapPolygonBean.PolygonListBean>>> polygonList = bean.getPolygonList();

        for (int i = 0; i < polygonList.size(); i++) {
            polygonOptions = new PolygonOptions();
            for (int k = 0; k < polygonList.get(i).size(); k++) {
                polygonHoleOptions = new PolygonHoleOptions();
                latLngHoles = new ArrayList<>();
                for (int j = 0; j < polygonList.get(i).get(k).size(); j++) {
                    LatLng latLng = new LatLng(polygonList.get(i).get(k).get(j).getLatitude(), polygonList.get(i).get(k).get(j).getLongitude());
                    if (k == 0) {
                        //围栏
                        latLngs.add(latLng);
                        polygonOptions.add(latLng);
                    } else {
                        //挖空
                        latLngHoles.add(latLng);
                    }
                }
                if (latLngHoles.size() > 0) {
                    polygonHoleOptions.addAll(latLngHoles);
                    polygonOptions.addHoles(polygonHoleOptions);
                }
            }
            polygonOptions.strokeWidth(5); // 多边形的边框
            polygonOptions.strokeColor(Color.parseColor("#0288FF")); // 边框颜色
            polygonOptions.fillColor(Color.argb(30, 2, 136, 255));   // 多边形的填充色
            aMap.addPolygon(polygonOptions);
        }
    }

    /**
     * 某个点是否在区域内
     *
     * @param latLngList 区域坐标合集
     * @param latLng     需要判断的点
     * @return
     */
    public boolean polygonCon(List<LatLng> latLngList, LatLng latLng) {
        PolygonOptions options = new PolygonOptions();
        for (LatLng i : latLngList) {
            options.add(i);
        }
        options.visible(false); //设置区域是否显示
        Polygon polygon = aMap.addPolygon(options);
        boolean contains = polygon.contains(latLng);
        polygon.remove();
        return contains;
    }

    /**
     * 监听屏幕中心坐标
     */
    AMap.OnCameraChangeListener cameraChangeListener = new AMap.OnCameraChangeListener() {

        @Override
        public void onCameraChange(CameraPosition cameraPosition) {

        }

        @Override
        public void onCameraChangeFinish(CameraPosition cameraPosition) {
            LatLng target = cameraPosition.target;

            LatLonPoint latLonPoint = new LatLonPoint(target.latitude, target.longitude);

            String deepType = "汽车服务|汽车销售|汽车维修|摩托车服务|餐饮服务|购物服务|生活服务|体育休闲服务|医疗保健服务|住宿服务|风景名胜|商务住宅|政府机构及社会团体|科教文化服务|交通设施服务|金融保险服务|公司企业|道路附属设施|地名地址信息|公共设施|通行设施";
            PoiSearch.Query query = new PoiSearch.Query("", deepType, "");
            //keyWord表示搜索字符串，
            //第二个参数表示POI搜索类型，二者选填其一，选用POI搜索类型时建议填写类型代码，码表可以参考下方（而非文字）
            //cityCode表示POI搜索区域，可以是城市编码也可以是城市名称，也可以传空字符串，空字符串代表全国在全国范围内进行搜索
            query.setPageSize(10);// 设置每页最多返回多少条poiitem
            query.setPageNum(1);//设置查询页码
            query.setDistanceSort(true);//设置是否按距离排序
            query.setLocation(latLonPoint);//设置搜索中心经纬度
            PoiSearch poiSearch = null;
            try {
                poiSearch = new PoiSearch(context, query);
            } catch (AMapException e) {
                e.printStackTrace();
            }
            poiSearch.setBound(new PoiSearch.SearchBound(latLonPoint, 10000));//设置周边搜索的中心点以及半径
            poiSearch.setOnPoiSearchListener(poiListener);
            poiSearch.searchPOIAsyn();
        }
    };

    /**
     * 监听POI搜索结果
     */
    PoiSearch.OnPoiSearchListener poiListener = new PoiSearch.OnPoiSearchListener() {

        @Override
        public void onPoiSearched(PoiResult poiResult, int i) {
            String mLocation = "";
            if (i == 1000) {
                List<PoiItem> pois = poiResult.getPois();
                if (pois.size()>0){
                    LocationBean locationBean = new LocationBean();
                    locationBean.setLongitude(poiResult.getQuery().getLocation().getLongitude());
                    locationBean.setLatitude(poiResult.getQuery().getLocation().getLatitude());
                    locationBean.setCity(pois.get(0).getCityName());
                    locationBean.setAoiName(pois.get(0).getTitle());
                    locationBean.setAddress(pois.get(0).getSnippet());
                    mLocation = new Gson().toJson(locationBean);
                }
            }
            Log.e("反地理编码", "发送信息: " + mLocation);
            mChannel.invokeMethod("getLocation", mLocation);
        }

        @Override
        public void onPoiItemSearched(PoiItem poiItem, int i) {

        }
    };

    /**
     * 区域缩放
     */
    public void boundsZoom(List<LatLng> latLngs) {
        if (latLngs == null) {
            return;
        }
        LatLngBounds.Builder builder = new LatLngBounds.Builder();
        for (int i = 0; i < latLngs.size(); i++) {
            builder.include(latLngs.get(i));
        }
        int padding = LittleUtils.dp2px(context,50);
        aMap.animateCamera(
                CameraUpdateFactory.newLatLngBoundsRect(
                        builder.build(),
                        padding,//左
                        padding,//右
                        padding,//上
                        padding//下
                )
        );
    }

    /**
     * 将屏幕中心定位到围栏内
     */
    public void polygonInside(AMapPolygonBean bean) {

        List<LatLng> polygonLatLngs = new ArrayList<>();

        List<List<List<AMapPolygonBean.PolygonListBean>>> polygonList = bean.getPolygonList();
        for (int i = 0; i < polygonList.size(); i++) {
            for (int k = 0; k < polygonList.get(i).size(); k++) {
                for (int j = 0; j < polygonList.get(i).get(k).size(); j++) {
                    LatLng latLng = new LatLng(polygonList.get(i).get(k).get(j).getLatitude(), polygonList.get(i).get(k).get(j).getLongitude());
                    if (k == 0) {
                        //围栏
                        polygonLatLngs.add(latLng);
                    }
                }
            }
        }

        if (polygonLatLngs == null) {
            return;
        }
        LatLngBounds.Builder builder = new LatLngBounds.Builder();
        for (int i = 0; i < polygonLatLngs.size(); i++) {
            builder.include(polygonLatLngs.get(i));
        }

        aMap.animateCamera(
                CameraUpdateFactory.newLatLngBoundsRect(
                        builder.build(),
                        0,//左
                        0,//右
                        0,//上
                        0//下
                )
        );
    }


}
